package com.gokzzz.quartz;

import com.gokzzz.util.SpringContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;

/**
 * 执行定时任务
 *
 * @author ganfujia
 * @date 2022/4/21 15:08
 */
@Slf4j
public class QuartzRunnable implements Callable<Object> {
    private final Object target;
    private final Method method;
    private final String params;

    QuartzRunnable(String beanName, String methodName, String params)
            throws NoSuchMethodException, SecurityException {
        this.target = SpringContextHolder.getBean(beanName);
        this.params = params;

        if (StringUtils.isNotBlank(params)) {
            List<Object[]> methodParams = getMethodParams(params);
            Class<?>[] methodParamsType = getMethodParamsType(methodParams);
            this.method = target.getClass().getDeclaredMethod(methodName, methodParamsType);
        } else {
            this.method = target.getClass().getDeclaredMethod(methodName);
        }
    }

    @Override
    public Object call() throws Exception {
        ReflectionUtils.makeAccessible(method);
        if (StringUtils.isNotBlank(params)) {
            List<Object[]> methodParams = getMethodParams(params);
            Object[] methodParamsValue = getMethodParamsValue(methodParams);
            method.invoke(target, methodParamsValue);
        } else {
            method.invoke(target);
        }
        return null;
    }

    /**
     * 获取method方法参数相关列表
     *
     * @param str 目标字符串
     * @return method方法相关参数列表
     */
    private List<Object[]> getMethodParams(String str) {
        String[] strs = str.split(",");
        List<Object[]> classs = new LinkedList<>();
        for (String s : strs) {
            String targetStr = StringUtils.trimToEmpty(s);
            // String字符串类型，以'或"开头
            if (StringUtils.startsWithAny(targetStr, "'", "\"")) {
                classs.add(new Object[]{targetStr, String.class});
            }
            // boolean布尔类型，等于true或者false
            else if ("true".equalsIgnoreCase(targetStr) || "false".equalsIgnoreCase(targetStr)) {
                classs.add(new Object[]{Boolean.valueOf(targetStr), Boolean.class});
            }
            // long长整形，以L结尾
            else if (StringUtils.endsWith(targetStr, "L")) {
                classs.add(new Object[]{Long.valueOf(StringUtils.substring(targetStr,0,targetStr.length() - 1)), Long.class});
            }
            // double浮点类型，以D结尾
            else if (StringUtils.endsWith(targetStr, "D")) {
                classs.add(new Object[]{Double.valueOf(StringUtils.substring(targetStr,0,targetStr.length() - 1)), Double.class});
            }
            // 其他类型归类为整形
            else {
                classs.add(new Object[]{Integer.valueOf(targetStr), Integer.class});
            }
        }
        return classs;
    }
    /**
     * 获取参数值
     *
     * @param methodParams 参数相关列表
     * @return 参数值列表
     */
    private Object[] getMethodParamsValue(List<Object[]> methodParams) {
        Object[] classs = new Object[methodParams.size()];
        int index = 0;
        for (Object[] os : methodParams) {
            classs[index] = os[0];
            index++;
        }
        return classs;
    }

    /**
     * 获取参数类型
     *
     * @param methodParams 参数相关列表
     * @return 参数类型列表
     */
    private Class<?>[] getMethodParamsType(List<Object[]> methodParams) {
        Class<?>[] classs = new Class<?>[methodParams.size()];
        int index = 0;
        for (Object[] os : methodParams) {
            classs[index] = (Class<?>) os[1];
            index++;
        }
        return classs;
    }
}
